// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package cn.org.dbtools.star.stack.connector;

import cn.org.dbtools.star.stack.constant.ConstantDef;
import cn.org.dbtools.star.stack.entity.ClusterInfoEntity;
import cn.org.dbtools.star.stack.exception.StarRequestException;
import cn.org.dbtools.star.stack.model.palo.ClusterOverviewInfoExt;
import cn.org.dbtools.star.stack.model.palo.StarResponseEntity;
import cn.org.dbtools.star.stack.util.CredsUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class StarStatisticClient extends StarClient {
    protected HttpClientPoolManager poolManager;

    @Autowired
    public StarStatisticClient(HttpClientPoolManager poolManager) {
        this.poolManager = poolManager;
    }

    @Autowired
    private StarMetaInfoClient metaInfoClient;

    public ClusterOverviewInfoExt getClusterInfo(ClusterInfoEntity entity) throws Exception {
        //转换json为需要的格式
//        response.getData();
        Map<String, Object> clusterInfoMap = new HashMap<>();
        //dbCount
        List<String> dbList = metaInfoClient.getDatabaseList(ConstantDef.STAR_DEFAULT_NS, entity);
        clusterInfoMap.put("dbCount", dbList.size());
        //tblCount
        List<String> tableList = metaInfoClient.getAllTableList(entity);
        clusterInfoMap.put("tblCount", tableList.size());

        //feCount
        List<String> feList = metaInfoClient.getFeList(entity);
        clusterInfoMap.put("feCount", feList.size());
        List<List<String>> beInfoList = metaInfoClient.getBeInfoList(entity);
        //beCount
        clusterInfoMap.put("beCount", beInfoList.size());
        float totalDisk = 0F;
        float minRemainDisk = 0F;
        float maxCpuOccupancy = 0F;
        float maxRamOccupancy = 0F;
        // 取使用量最高的磁盘占用返回
        for (List<String> beInfo : beInfoList) {
            float remainDiskTmp = Float.valueOf(beInfo.get(13).replace("KB", "").replace("MB", "")
                    .replace("GB", "").replace("TB", "").trim());
            if (minRemainDisk == 0F || minRemainDisk > remainDiskTmp) {
                minRemainDisk = remainDiskTmp;
                totalDisk = totalDisk + Float.valueOf(beInfo.get(14).replace("KB", "").replace("MB", "")
                        .replace("GB", "").replace("TB", "").trim());
            }
            float cpuOccupancyTmp = Float.valueOf(beInfo.get(25).replace("%", "").trim());
            float ramOccupancyTmp = Float.valueOf(beInfo.get(24).replace("%", "").trim());
            if (maxCpuOccupancy == 0F || maxCpuOccupancy < cpuOccupancyTmp) {
                maxCpuOccupancy = cpuOccupancyTmp;
            }
            if (maxRamOccupancy == 0F || maxRamOccupancy < ramOccupancyTmp) {
                maxRamOccupancy = ramOccupancyTmp;
            }
        }
        float diskOccupancy = totalDisk - minRemainDisk;
        //diskOccupancy
        clusterInfoMap.put("cpuOccupancy", maxCpuOccupancy);
        //diskOccupancy
        clusterInfoMap.put("ramOccupancy", maxRamOccupancy);
        //diskOccupancy
        clusterInfoMap.put("diskOccupancy", diskOccupancy);
        //remainDisk
        clusterInfoMap.put("remainDisk", Math.round(minRemainDisk));

        return JSON.parseObject(JSON.toJSONString(clusterInfoMap), ClusterOverviewInfoExt.class);
    }

    public boolean testFeHealthyWithHttpApi(String feHttpHost, int feHttpPort, String username, String password) {
        String healthyURL = "http://" + feHttpHost + ":" + feHttpPort + "/api/bootstrap";

        try {
            Map<String, String> headers = Maps.newHashMap();
            setHeaders(headers);
            setGetHeaders(headers);
            if (password == null || password.isEmpty()) {
                setAuthHeaders(headers, username, null);
            } else {
                setAuthHeaders(headers, username, CredsUtil.tryAesDecrypt(password));
            }

            StarResponseEntity response = poolManager.doGet(healthyURL, headers, LOGIN_SUCCESS_CODE);
            if (response.getCode() != LOGIN_SUCCESS_CODE) {
                throw new StarRequestException("Login star error:" + response.getData());
            }

            log.info("fe http health return: {}", response.getData());
            // or status == ok
            JSONObject stateJson = JSONObject.parseObject(response.getData());
            String status = stateJson.getString("status");
            if (status != null && status.equals("OK")) {
                log.info(" fe {}:{} http health is normal, return status OK", feHttpHost, feHttpPort);
                return true;
            }
        } catch (Exception e) {
            log.error("{} syntax error {}", healthyURL, e.getMessage());
            return false;
        }
        return false;
    }
}
